from django.test import TestCase


from django.core.urlresolvers import reverse
from django.utils import timezone
import json
import md5

from models import User, Category, Message

# Create your tests here.

def create_user(username, nickname, password):
    """
    Create users in test environment, with password md5 hashed.
    """
    return User.objects.create(
            username=username,
            nickname=nickname,
            passkey =md5.new(password).hexdigest()
    )

def create_category(description):
    """
    Create descriptons in test environment
    """
    return Category.objects.create(
            description=description
    )

def create_message(user, category, content, time, latitude, longitude):
    """
    Create a message.
    """
    return Message.objects.create(
            user=user,
            category=category,
            content=content,
            time=time,
            latitude=latitude,
            longitude=longitude
    )

class RegieterViewTests(TestCase):
    def test_register_view_with_valid_info(self):
        userinfo = {
            "username": "test",
            "nickname": "testy",
            "password": "testpassword",
        }
        response = self.client.post(reverse('backend:register'), {'json': json.dumps(userinfo),})
        user = User.objects.get(username=userinfo['username'])
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")
        self.assertEqual(user.nickname, userinfo['nickname'])
        self.assertEqual(user.passkey, md5.new(userinfo['password']).hexdigest())

    def test_register_view_with_user_exists(self):
        create_user("test1", "test1y", "test1p")
        userinfo = {
            "username": "test1",
            "nickname": "test2y",
            "password": "test2p"
        }
        response = self.client.post(reverse('backend:register'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "username exists")
        self.assertEqual(
            User.objects.get(username=userinfo['username']).nickname,
            "test1y"
        )

class LoginViewTests(TestCase):
    def test_login_view_with_valid_info(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "test",
            "password": "testp"
        }
        response = self.client.post(reverse('backend:login'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")

    def test_login_view_with_wrong_username(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "teste",
            "password": "testp"
        }
        response = self.client.post(reverse('backend:login'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")

    def test_login_view_with_wrong_password(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "test",
            "password": "testpp"
        }
        response = self.client.post(reverse('backend:login'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")


class PublishViewTests(TestCase):
    def test_publish_view_with_valid_info(self):
        create_user("test", "testy", "testp")
        create_category("default")
        publishinfo = {
            "username": "test",
            "password": "testp",
            "content":  "Hello, world!",
            "latitude":  89.1,
            "longitude": -50.2
        }
        response = self.client.post(reverse('backend:publish'), {'json': json.dumps(publishinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")
        self.assertEqual(
            Message.objects.all().exists(),
            True
        )
        self.assertEqual(
            Message.objects.get(content="Hello, world!").latitude,
            publishinfo['latitude']
        )

    def test_publish_view_with_wrong_user_info(self):
        create_user("test", "testy", "testp")
        create_category("default")
        publishinfo = {
            "username": "testt",
            "password": "testp",
            "content":  "Hello, world!",
            "latitude":  89.1,
            "longitude": -50.2
        }
        response = self.client.post(reverse('backend:login'), {'json': json.dumps(publishinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")
        self.assertEqual(
            Message.objects.all().exists(),
            False
        )

class ResetasswordViewTests(TestCase):
    def test_resetpassword_view_with_valid_info(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "test",
            "password": "testp",
            "new password": "testpppppp"
        }
        response = self.client.post(reverse('backend:resetpassword'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")
        self.assertEqual(
            User.objects.get(username=userinfo['username']).passkey,
            md5.new(userinfo['new password']).hexdigest()
        )

    def test_resetpassword_view_with_wrong_password(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "test",
            "password": "testpp",
            "new password": "testpppppp"
        }
        response = self.client.post(reverse('backend:resetpassword'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")

    def test_resetpassword_view_with_wrong_username(self):
        create_user("test", "testy", "testp")
        userinfo = {
            "username": "tast",
            "password": "testp",
            "new password": "testpppppp"
        }
        response = self.client.post(reverse('backend:resetpassword'), {'json': json.dumps(userinfo),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")

class FetchViewTests(TestCase):
    def test_fetch_view_with_valid_info(self):
        user1 = create_user("u1", "u1n", "u1p")
        user2 = create_user("u2", "u2n", "u2p")
        user3 = create_user("u3", "u3n", "u3p")
        cate  = create_category("default")
        create_message(user1, cate, "I'm user 1", timezone.now(), 23.065097, 113.397912) # SYSU EAST CENTER GARDEN
        create_message(user2, cate, "I'm user 2", timezone.now(), 23.073027, 113.398361) # SYSU EAST LIBRARY
        create_message(user3, cate, "I'm user 3", timezone.now(), 23.071598, 113.379479) # GUAN ZHOU ISLAND
        fetch_info = {
            "username": "u1",
            "password": "u1p",
            "latitude": 23.065097,
            "longitude": 113.397912,
            "distance": 0
        }
        response = self.client.post(reverse('backend:fetch'), {'json': json.dumps(fetch_info),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")
        self.assertContains(response, "I'm user 1")
        self.assertContains(response, "I'm user 2")
        self.assertContains(response, "I'm user 3")

class DeletemsgViewTests(TestCase):
    def test_deletemsg_with_valid_info(self):
        user = create_user("test", "testy", "testp")
        cate = create_category("default")
        msg  = create_message(user, cate, "hello world", timezone.now(), -89, 100)
        task_info = {
            "username": "test",
            "password": "testp",
            "message id": msg.id
        }
        response = self.client.post(reverse('backend:deletemsg'), {'json': json.dumps(task_info),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "success")
        self.assertEqual(
            Message.objects.all().exists(),
            False
        )

    def test_deletemsg_with_wrong_username(self):
        user = create_user("test", "testy", "testp")
        cate = create_category("default")
        msg  = create_message(user, cate, "hello world", timezone.now(), -89, 100)
        task_info = {
            "username": "tast",
            "password": "testp",
            "message id": msg.id
        }
        response = self.client.post(reverse('backend:deletemsg'), {'json': json.dumps(task_info),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")
        self.assertEqual(
            Message.objects.all().exists(),
            True
        )

    def test_deletemsg_with_wrong_password(self):
        user = create_user("test", "testy", "testp")
        cate = create_category("default")
        msg  = create_message(user, cate, "hello world", timezone.now(), -89, 100)
        task_info = {
            "username": "test",
            "password": "testppp",
            "message id": msg.id
        }
        response = self.client.post(reverse('backend:deletemsg'), {'json': json.dumps(task_info),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "invalid username or password")
        self.assertEqual(
            Message.objects.all().exists(),
            True
        )


    def test_deletemsg_with_message_not_exists(self):
        user = create_user("test", "testy", "testp")
        cate = create_category("default")
        msg  = create_message(user, cate, "hello world", timezone.now(), -89, 100)

        yauser = create_user("yatest", "yatesty", "yatestp")
        task_info = {
            "username": "yatest",
            "password": "yatestp",
            "message id": msg.id
        }
        response = self.client.post(reverse('backend:deletemsg'), {'json': json.dumps(task_info),})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "fail")
        self.assertContains(response, "message not exists")
        self.assertEqual(
            Message.objects.all().exists(),
            True
        )
